package framework.eea.entity;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import framework.eea.StateBasedGame;
import framework.eea.event.Component;
import framework.eea.gui.JFrameGameContainer;
import framework.eea.gui.Graphics;

public class Entity implements Serializable {

    private String id;
    private boolean passable;
    private Point position;
    private float rotation;
    private float scale;
    private Dimension size;
    private boolean visible;
    private List<Component> events;

    public Entity(String entityID) {
        id = entityID;

        events = new LinkedList<Component>();

        position = new Point(0, 0);
        scale = 1;
        rotation = 0;
        visible = true;
        passable = true;
    }

    public void addComponent(Component event) {
        // directly skip the rest if the event passed in is null
        if (event == null) {
            return;
        }

        // assign the associations: the entity owning "event" is "this";
        // "event" is a new event for this entity
        event.setOwnerEntity(this);
        events.add(event);
    }

    public boolean collides(Entity otherEntity) {
  
        if (otherEntity == null || (id != null && id.equals(otherEntity.getID()))) {
            return false;
        }
        
        return getShape().intersects(otherEntity.getShape().getBounds().x, otherEntity.getShape().getBounds().y,
                                     otherEntity.getShape().getBounds().width, otherEntity.getShape().getBounds().height);
    }

    
    public Component getEvent(String id) {
        if (id == null) {
            return null;
        }
        // loop over all components
        for (Component comp : events) {
            // once the first component with the target ID is found, return it
            if (id.equalsIgnoreCase(comp.getId())) {
                return comp;
            }
        }

        return null;
    }

    
    public String getID() {
        return id;
    }

    
    public Point getPosition() {
        return position;
    }

    
    public float getRotation() {
        return rotation;
    }

    
    public float getScale() {
        return scale;
    }

    
    public Shape getShape() {

        Rectangle rec = new Rectangle(new Point((int) (position.x - getSize().getWidth() / 2.0f), (int) (position.y - getSize().getHeight() / 2.0f)), 
                                      size);
        
        //TODO
        // rotate the shape as used for the actual object
        /*Shape shape = rec.transform(Transform.createRotateTransform(
                (float) Math.toRadians(rotation), position.x, position.y));*/
        
        return rec;
    }
    
    public Dimension getSize() {
        return size;
    }
        


    public boolean isPassable() {
        return passable;
    }

    
    public boolean isVisible() {
        return visible;
    }

    
    public void removeComponent(Component componentToRemove) {
        events.remove(componentToRemove);
    }

    public void removeComponent(String componentIDToRemove) {
        if (componentIDToRemove == null) {
            return;
        }

        // loop over all components
        for (int i = 0; i < events.size(); i++) {
            // if the component at position i has the correct ID, remove it
            if (componentIDToRemove.equalsIgnoreCase(events.get(i).getId())) {
                events.remove(i);
            }
        }
    }

    
    public void render(JFrameGameContainer gc, StateBasedGame sb, Graphics graphicsContext) {

    }

    
    public void setPassable(boolean canBePassed) {
        passable = canBePassed;
    }

    
    public void setPosition(Point newPosition) {
        position = newPosition;
    }

    
    public void setRotation(float newAngle) {
        rotation = newAngle;
    }

    
    public void setScale(float scaleFactor) {
        scale = scaleFactor;
    }

    
    public void setSize(Dimension newSize) {
        size = newSize;
    }

    
    public void setVisible(boolean isVisible) {
        visible = isVisible;
    }

    public Rectangle getRect() {
        return new Rectangle(
                getPosition().x-getSize().width/2, 
                getPosition().y-getSize().height/2, 
                getSize().width,
                getSize().height);
    }
    
    
    public void update(JFrameGameContainer gc, StateBasedGame sb, int delta) {
        // loop over all components and ask them to update themselves
        for (Component event : events) {
            if (event != null) // ask the current event to update itself
            {
                event.update(gc, sb, delta);
            }
        }
    }
}
